package ru.zombator.taskman.core.dbclient;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.UUID;

import ru.zombator.taskman.core.domain.IManager;
import ru.zombator.taskman.core.domain.ITask;
import ru.zombator.taskman.core.domain.ITaskProject;
import ru.zombator.taskman.core.domain.IWorker;

/**
 * Критерий выборки задач
 * 
 * @author nvamelichev
 * 
 */
public class TaskCriteria implements Serializable {
	private static final long serialVersionUID = 1L;

	/**
	 * связка между условиями в критерии
	 */
	public enum Clause {
		/**
		 * или
		 */
		OR,
		/**
		 * и
		 */
		AND
	}

	String name = null;
	Clause workerClause = Clause.OR;
	List<IWorker> workers = null;

	Clause managerClause = Clause.OR;
	List<IManager> managers = null;

	UUID projectId = null;

	Integer statusOrdinal = null;

	private String filterName(String name) {
		return "%" + name.replaceAll("\\W", "_") + "%";
	}

	/**
	 * Задает искомую подстроку в имени задачи
	 * 
	 * @param name
	 *            - искомое имя
	 * @return критерий
	 */
	public TaskCriteria withName(String name) {
		this.name = filterName(name);
		return this;
	}

	/**
	 * Задает список менеджеров, один или все из которых должны быть в проекте,
	 * в котором находится задача.
	 * 
	 * @param clause
	 *            - тип критерия по менеджерам: все (AND) или хотя бы один (OR)
	 * @param managers
	 *            - список менеджеров
	 * @return критерий
	 */
	public TaskCriteria withManagers(Clause clause, List<IManager> managers) {
		this.managers = new ArrayList<IManager>(managers);
		this.managerClause = clause;
		return this;
	}

	/**
	 * Задает список исполнителей, один или все из которых должны быть в
	 * проекте, в котором находится задача.
	 * 
	 * @param clause
	 *            - тип критерия по исполнителям: все (AND) или хотя бы один
	 *            (OR)
	 * @param workers
	 *            - список исполнителей
	 * @return критерий
	 */
	public TaskCriteria withWorkers(Clause clause, List<IWorker> workers) {
		this.workers = new ArrayList<IWorker>(workers);
		this.workerClause = clause;
		return this;
	}

	/**
	 * Задает проект, в котором должна находиться искомая задача
	 * 
	 * @param project
	 *            - проект
	 * @return критерий
	 */
	public TaskCriteria inProject(ITaskProject project) {
		this.projectId = project.getId();
		return this;
	}

	/**
	 * Задает состояние, которое должна иметь искомая задача
	 * 
	 * @param status
	 *            - состояние
	 * @return критерий
	 */
	public TaskCriteria withStatus(ITask.Status status) {
		this.statusOrdinal = status.ordinal();
		return this;
	}
}
